﻿using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;

namespace BizElements.Core
{
    /// <summary>
    /// Collection of <see cref="DbRelation"/> objects.
    /// </summary>
    [Serializable]
    internal sealed class DbRelationCollection : IEnumerable
    {
        #region Strong-typed collection.

        List<DbRelation> list = new List<DbRelation>();
        List<IDbTable> tables = new List<IDbTable>();

        /// <summary>
        /// Gets the relation that connects the specified tables. <b>Null</b> if it doesn't exist.
        /// </summary>
        public DbRelation this[IDbTable t1, IDbTable t2]
        {
            get
            {
                foreach (DbRelation relation in this.list)
                {
                    if (relation.Connects(t1, t2))
                        return relation;
                }

                return null;
            }
        }

        /// <summary>
        /// Gets the relation at the specifed index.
        /// </summary>
        public DbRelation this[int index]
        {
            get { return this.list[index]; }
        }

        /// <summary>
        /// Gets the number of relations in the colection.
        /// </summary>
        public int Count
        {
            get { return this.list.Count; }
        }

        /// <summary>
        /// Gets the tables used by relations in this collection.
        /// </summary>
        public IDbTable[] Tables
        {
            get { return this.tables.ToArray(); }
        }

        /// <summary>
        /// Adds a relation with a unique name to the collection.
        /// If a relation with the same name already exists, a new name is automatically set.
        /// </summary>
        /// <param name="relation">New relation.</param>
        public void Add(DbRelation relation)
        {
            int i = 2;
            while (GetByName(relation.Name) != null)
            {
                relation.Name += "_" + i.ToString(CultureInfo.InvariantCulture);
                i++;
            }

            this.list.Add(relation);

            if (this.tables.Contains(relation.Parent) == false)
                this.tables.Add(relation.Parent);

            if (this.tables.Contains(relation.Child) == false)
                this.tables.Add(relation.Child);
        }

        /// <summary>
        /// Gets the relation with the specified name.
        /// </summary>
        /// <param name="name">Relation name.</param>
        /// <returns>Relation or <b>null</b> if it doesn't exist.</returns>
        public DbRelation GetByName(string name)
        {
            foreach (DbRelation candidate in this.list)
            {
                if (candidate.Name == name)
                    return candidate;
            }

            return null;
        }        

        /// <summary>
        /// Converts the collection to an array of DbRelation object.
        /// </summary>
        /// <returns>An array of DbRelation object</returns>
        public DbRelation[] ToArray()
        {
            return this.list.ToArray();            
        }

        #endregion

        #region IEnumerable.

        /// <summary>
        /// Gets an enumerator that can iterate through DbColumnCollection.
        /// </summary>
        public IEnumerator GetEnumerator()
        {
            return this.list.GetEnumerator();
        }

        #endregion
    }
}